package club.ruanx.auth.service;

import club.ruanx.acl.entity.SysUser;
import club.ruanx.acl.repository.SysRoleRepository;
import club.ruanx.acl.repository.SysUserRepository;
import club.ruanx.security.bean.UserAuthInfo;
import club.ruanx.security.bean.UserAuthInfoContextHolder;
import club.ruanx.util.ServletContextUtils;
import club.ruanx.util.StringUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author 阮胜
 * @date 2018/8/4 16:35
 */
@Component
@Qualifier("userDetailService")
public class UserDetailServiceImpl implements UserDetailsService {
    private static final String USER_NOT_EXIST = "用户不存在";
    private static final String ROLE_PREFIX = "ROLE_";
    private static final String ROLE_DELIMITED = ",";
    private static final String LOGIN_TYPE = "type";
    private static final String LOGIN_TYPE_PHONE = "phone";
    private final SysUserRepository sysUserRepository;
    private final SysRoleRepository sysRoleRepository;

    public UserDetailServiceImpl(SysUserRepository sysUserRepository, SysRoleRepository sysRoleRepository) {
        this.sysUserRepository = sysUserRepository;
        this.sysRoleRepository = sysRoleRepository;
    }


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //从上下文中获取当前登录类型
        String loginType = ServletContextUtils.getCurrentRequest().getParameter(LOGIN_TYPE);
        Optional<SysUser> sysUserOptional;
        //根据登录类型使用不同发起不同的查询
        if (StringUtils.isEmpty(loginType)) {
            sysUserOptional = sysUserRepository.findByUsername(username);
        } else if (LOGIN_TYPE_PHONE.equalsIgnoreCase(loginType)) {
            sysUserOptional = sysUserRepository.findByPhone(username);
        } else {
            sysUserOptional = Optional.empty();
        }
        //如果用户不存在则抛出异常
        SysUser sysUser = sysUserOptional.orElseThrow(() -> new UsernameNotFoundException(USER_NOT_EXIST));
        List<String> sysUserRoles = generateRoles(sysUser.getRoles());
        //将用户角色信息转换成字符串格式
        String roles = StringUtils.collectionToDelimitedString(sysUserRoles, ROLE_DELIMITED);
        List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList(roles);
        //生成用户授权信息类
        UserAuthInfo userAuthInfo = UserAuthInfo.builder().uid(sysUser.getId()).username(username)
                .roles(sysUserRoles).build();
        //在用户授权信息上下文中设置用户授权信息
        UserAuthInfoContextHolder.setUserAuthInfo(userAuthInfo);
        UserAuthInfoContextHolder.setSysUser(sysUser);
        return new User(sysUser.getUsername(), sysUser.getPassword()
                , authorities);
    }

    private List<String> generateRoles(String roles) {
        if (StringUtils.isEmpty(roles)) {
            return null;
        }
        String[] rolesArr = roles.split(",");
        Integer[] rolesIntArr = new Integer[rolesArr.length];
        for (int i = 0; i < rolesArr.length; i++) {
            rolesIntArr[i] = Integer.valueOf(rolesArr[i]);
        }
        return sysRoleRepository.findByIdIn(rolesIntArr)
                .stream()
                .map(sysRole -> ROLE_PREFIX.concat(sysRole.getName()))
                .collect(Collectors.toList());
    }
}
